package com.qys.livesMall.shop.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.esotericsoftware.minlog.Log;
import com.qys.livesMall.app.user.constants.AppUserConstant;
import com.qys.livesMall.app.user.mapper.UserShopStatisticsMapper;
import com.qys.livesMall.app.user.model.dto.sys.UserQuery;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.model.entity.H2AppUserBank;
import com.qys.livesMall.app.user.model.entity.IpOperateStatistics;
import com.qys.livesMall.app.user.model.entity.UserShopStatistics;
import com.qys.livesMall.app.user.service.*;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.exception.enums.ExceptionEnum;
import com.qys.livesMall.common.message.MessageServer;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.common.utils.bean.BeanProUtils;
import com.qys.livesMall.finance.common.Constant;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.enums.AccountTradeTypeEnum;
import com.qys.livesMall.finance.enums.AccountTypeEnum;
import com.qys.livesMall.finance.model.dto.AccountHandle;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.model.entity.shop.FinanceShopAccount;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.finance.service.FinanceShopAccountDetailService;
import com.qys.livesMall.finance.service.FinanceShopAccountService;
import com.qys.livesMall.finance.util.BusinessNoUtil;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.Paging;
import com.qys.livesMall.framework.view.QysPage;
import com.qys.livesMall.shop.constants.ShopConstant;
import com.qys.livesMall.shop.dao.H2ShopBaseDao;
import com.qys.livesMall.shop.dao.H2ShopRechargeWithdrawalDao;
import com.qys.livesMall.shop.enums.ShopEventTypeEnum;
import com.qys.livesMall.shop.enums.ShopMessageEnum;
import com.qys.livesMall.shop.event.ShopEvent;
import com.qys.livesMall.shop.event.shop.pojo.ShopRechargeWithdrawalPojo;
import com.qys.livesMall.shop.event.shop.pojo.ShopWaitWlPojo;
import com.qys.livesMall.shop.mapper.H2ShopBaseMapper;
import com.qys.livesMall.shop.mapper.H2ShopRechargeWithdrawalMapper;
import com.qys.livesMall.shop.modal.dto.shop.ShopQuery;
import com.qys.livesMall.shop.modal.dto.shop.rw.AuditRw;
import com.qys.livesMall.shop.modal.dto.shop.rw.CancelRw;
import com.qys.livesMall.shop.modal.dto.shop.rw.EditRw;
import com.qys.livesMall.shop.modal.dto.shop.rw.ShopRwSearch;
import com.qys.livesMall.shop.modal.dto.shop.rwnew.ShopWlSearch;
import com.qys.livesMall.shop.modal.dto.shop.rwnew.ShopRechargeSearch;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.modal.vo.*;
import com.qys.livesMall.shop.modal.vo.rw.RechargeVO;
import com.qys.livesMall.shop.service.H2ShopBaseService;
import com.qys.livesMall.shop.service.H2ShopRechargeWithdrawalService;
import com.qys.livesMall.shop.service.H2ShopStatisticsInfoService;
import com.qys.livesMall.shop.service.ShopRechargeGradientService;
import com.qys.livesMall.system.model.entity.H2Channel;
import com.qys.livesMall.system.service.IH2SysConfigService;
import com.qys.livesMall.system.service.SysH2ChannelService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 店铺充值提现表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-06-06
 */
@Service
public class ShopRechargeWithdrawalServiceImpl  implements H2ShopRechargeWithdrawalService {

    @Autowired
    private MessageServer messageServer;
    @Autowired
    private H2ShopBaseDao shopBaseDao;
    @Autowired
    private IH2AppUserService appUserService;
    @Autowired
    private IH2AppUserBankService userBankService;

    @Autowired
    private H2ShopRechargeWithdrawalDao rechargeWithdrawalDao;

    @Autowired
    private H2ShopRechargeWithdrawalMapper rechargeWithdrawalMapper;

    @Autowired
    private IH2SysConfigService sysConfigService;

    @Autowired
    private FinanceBusinessService financeBusinessService;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private UserShopStatisticsMapper userShopStatisticsMapper;
    @Resource
    private H2ShopStatisticsInfoService h2ShopStatisticsInfoService;
    @Autowired
    private FinanceShopAccountService financeShopAccountService;
    @Autowired
    private FinanceShopAccountDetailService financeShopAccountDetailService;
    @Autowired
    private ShopRechargeGradientService shopRechargeGradientService;

    @Resource
    private AppUserRelationService relationService;

    @Autowired
    private H2ShopBaseService shopBaseService;
    @Resource
    private UserShopStatisticsService userShopStatisticsService;

    @Resource
    private SysH2ChannelService channelService;
    @Autowired
    private IpOperateStatisticsService ipOperateStatisticsService;

    @Override
    public QysPage<ShopRechargeWithdrawalVO> search(ShopRwSearch search) {
        if (search.getShopCode()!=null) {
            H2ShopBase shop = shopBaseDao.getByShopCode(search.getShopCode());
            if (shop == null) {
                return QysPage.build(search);
            }
            search.setShopId(shop.getId());
        }
        Paging<H2ShopRechargeWithdrawal> page=rechargeWithdrawalMapper.search(new Paging<>(search));

        List<ShopRechargeWithdrawalVO> vos=new ArrayList<>();
        page.getRecords().forEach(e->{
            ShopRechargeWithdrawalVO vo= BeanProUtils.copyProperties(e,ShopRechargeWithdrawalVO::new);
            vos.add(vo);
        });
        return QysPage.build(search).setRecords(vos).setTotal(page.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R recharge(EditRw rw) {
        rwCheck(rw);
        H2ShopBase shop=shopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (shop==null||!Objects.equals(shop.getStatus(), ShopConstant.ShopStatus.IN_BUSINESS)){
            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);
        }
        H2AppUserBank bank=userBankService.getById(rw.getCardId());
        if (bank==null){
            return messageServer.failMsg(ShopMessageEnum.SHOP_PAY_ACCOUNT_ERROR);
        }
        H2ShopRechargeWithdrawal shopRw=new H2ShopRechargeWithdrawal();
        shopRw.setUserId(SecurityUtils.getUserId());
        shopRw.setShopId(shop.getId());
        shopRw.setOrderNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_RECHARGE));
        shopRw.setType(AccountBusinessTypeEnum.SHOP_RECHARGE.getType());
        shopRw.setAmount(rw.getAmountIncurred());
        shopRw.setActualArrivalAmount(new BigDecimal("0"));
        shopRw.setPayMethod(rw.getPayMethod());
        shopRw.setVoucherImg(rw.getVoucherImg());
        shopRw.setAccountId(Long.valueOf(bank.getId()));
        shopRw.setAccountNumber(bank.getBankNo());
        shopRw.setAccountName(bank.getBankUserName());
        shopRw.setAccountUserName(bank.getBankUserName());
        shopRw.setChannelId(rw.getChannelId());
        shopRw.setCreateDate(LocalDateTime.now());
        shopRw.setStatus(ShopConstant.RWStatus.WAIT_AUDIT);
        shopRw.setDescription(rw.getDescription());
        shopRw.setFirstRecharge(Constants.YesNoInt.NO);
        FinanceShopAccount financeShopAccount = financeShopAccountService.get(shopRw.getUserId());
        if (null != financeShopAccount){
            shopRw.setAmountBeforeChange(financeShopAccount.getAvailableBalance());
        }
        //转账
        FinancePayDTO payDTO = new FinancePayDTO();
        payDTO.setUserId(Long.valueOf(shopRw.getUserId()));
        payDTO.setShopId(shopRw.getShopId());
        payDTO.setBusinessNo(shopRw.getOrderNo());
        payDTO.setAmountIncurred(shopRw.getAmount());
        payDTO.setDescription(shopRw.getDescription());
        payDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_APPLY_FOR);
        financeBusinessService.pay(payDTO);
        if (!payDTO.getSuccess()) {
            throw new QysException(payDTO.getMessage());
        }

        boolean save = rechargeWithdrawalDao.save(shopRw);
        if(save){
            try {
                LambdaQueryWrapper<UserShopStatistics> queryWrapper = Wrappers.lambdaQuery(UserShopStatistics.class)
                        .eq(UserShopStatistics::getUserId, SecurityUtils.getUserId());
                List<UserShopStatistics> userShopStatistics = userShopStatisticsMapper.selectList(queryWrapper);
                if(CollectionUtils.isNotEmpty(userShopStatistics)){
                    UserShopStatistics userShopData = userShopStatistics.get(0);
 /*                   if(userShopData.getFirstCharge() == null){
                        userShopData.setFirstCharge(LocalDateTime.now());
                        userShopStatisticsMapper.updateById(userShopData);
                    }*/
                }
            } catch (Exception e) {
                Log.info("更新店铺首充时间失败,shop:[{}]",shop.getId()+"");
            }
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R withdrawal(EditRw rw) {
        String val = sysConfigService.getConfigKey("4dbcb4f49f3915e98d67344b015013f8");
        if(rw.getAmountIncurred().compareTo(new BigDecimal(val)) < 0){
            throw new QysException(MessageUtils.message("exceed.max.money"));
        }

        rwCheck(rw);
        //检查是否存在待审核提现单
        H2ShopRechargeWithdrawal oldRw=rechargeWithdrawalDao.getWaitAuditWl(SecurityUtils.getUserId());
        if (oldRw!=null){
            return messageServer.failMsg(ShopMessageEnum.SHOP_WL_EXIST);
        }
        H2AppUser appUser = appUserService.getById(SecurityUtils.getUserId());
        if (null == appUser) {
            throw new QysException(MessageUtils.message("re.login"));
        }
        if (appUser.getStatus()==1){
            throw new QysException(MessageUtils.message("user.freeze.centre"));
        }
        H2ShopBase shop=shopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (shop==null||!Objects.equals(shop.getStatus(), ShopConstant.ShopStatus.IN_BUSINESS)){
            return messageServer.failMsg(ShopMessageEnum.SHOP_BALANCE_INSUFFICIENT);
        }
        H2AppUserBank bank=userBankService.getById(rw.getCardId());
        if (bank==null){
            return messageServer.failMsg(ShopMessageEnum.SHOP_PAY_ACCOUNT_ERROR);
        }
        H2ShopRechargeWithdrawal shopRw=new H2ShopRechargeWithdrawal();
        shopRw.setUserId(SecurityUtils.getUserId());
        shopRw.setShopId(shop.getId());
        shopRw.setOrderNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_WITHDRAWAL));
        shopRw.setType(AccountBusinessTypeEnum.SHOP_WITHDRAWAL.getType());
        shopRw.setAmount(rw.getAmountIncurred());
        shopRw.setActualArrivalAmount(new BigDecimal("0"));
        shopRw.setPayMethod(rw.getPayMethod());
        shopRw.setAccountId(Long.valueOf(bank.getId()));
        shopRw.setAccountNumber(bank.getBankNo());
        shopRw.setAccountName(bank.getBankUserName());
        shopRw.setAccountUserName(bank.getBankUserName());
        shopRw.setChannelId(rw.getChannelId());
        shopRw.setCreateDate(LocalDateTime.now());
        shopRw.setStatus(ShopConstant.RWStatus.WAIT_AUDIT);
        shopRw.setDescription(rw.getDescription());
        FinanceShopAccount financeShopAccount = financeShopAccountService.get(shopRw.getUserId());
        if (null != financeShopAccount){
            shopRw.setAmountBeforeChange(financeShopAccount.getAvailableBalance());
        }

        //扣款
        FinancePayDTO payDTO = new FinancePayDTO();
        payDTO.setUserId(Long.valueOf(shopRw.getUserId()));
        payDTO.setShopId(shopRw.getShopId());
        payDTO.setBusinessNo(shopRw.getOrderNo());
        payDTO.setAmountIncurred(shopRw.getAmount());
        payDTO.setDescription(shopRw.getDescription());
        payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_APPLY_FOR);

        financeBusinessService.pay(payDTO);
        if (!payDTO.getSuccess()){
            throw new QysException(payDTO.getMessage());
        }
        boolean save = rechargeWithdrawalDao.save(shopRw);
        if(save){
            try {
                applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                        .shopId(shopRw.getShopId())
                        .eventType(ShopEventTypeEnum.SHOP_WAIT_WL.getType())
                        .paramObj(ShopWaitWlPojo.builder()
                                .amount(shopRw.getAmount())
                                .type(1)
                                .build()
                        )
                        .build())
                );
            } catch (Exception e) {
                Log.info("提现审核监听异常,FinancePayDTO:[{}]", JSON.toJSONString(payDTO));
            }
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R auditPass(AuditRw auditRw){
        synchronized (auditRw.getId()) {
            H2ShopRechargeWithdrawal rw = rechargeWithdrawalDao.getById(auditRw.getId());
            if (rw == null) {
                return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_FIND_ORDER);
            }
            //提现不填实到金额
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL.getType(), rw.getType())){
                auditRw.setActualArrivalAmount(null);
            }
            if (auditRw.getActualArrivalAmount() != null && auditRw.getActualArrivalAmount().compareTo(new BigDecimal("0")) != 1) {
                throw new QysException(ShopMessageEnum.SHOP_AMOUNT_ERROR);
            }
            if (!Objects.equals(ShopConstant.RWStatus.WAIT_AUDIT, rw.getStatus())) {
                throw new QysException(ShopMessageEnum.SHOP_ORDER_STATUS_EXCEPTION);
            }
            rw.setStatus(ShopConstant.RWStatus.AUDITED);
            rw.setAuditDesc(auditRw.getAuditDesc());
            rw.setAuditDate(LocalDateTime.now());
            rw.setAuditUserName(SecurityUtils.getUsername());
            if (auditRw.getActualArrivalAmount() == null) {
                auditRw.setActualArrivalAmount(rw.getAmount());
            }
            rw.setActualArrivalAmount(auditRw.getActualArrivalAmount());
            BigDecimal difference=rw.getAmount().subtract(rw.getActualArrivalAmount());

            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(rw.getUserId()));
            payDTO.setShopId(rw.getShopId());
            payDTO.setBusinessNo(rw.getOrderNo());
            payDTO.setAmountIncurred(rw.getActualArrivalAmount());
            payDTO.setDescription(auditRw.getAuditDesc());
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_RECHARGE.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE);
                if (difference.compareTo(new BigDecimal("0"))<0){
                    FinancePayDTO differencePayDTO = new FinancePayDTO();
                    payDTO.setUserId(rw.getUserId());
                    payDTO.setShopId(rw.getShopId());
                    differencePayDTO.setBusinessNo(rw.getOrderNo());
                    differencePayDTO.setAmountIncurred(difference.abs());
                    differencePayDTO.setDescription("申请与实际差额");
                    differencePayDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE_APPLY_FOR);
                    financeBusinessService.pay(differencePayDTO);

                    if (!differencePayDTO.getSuccess()) {
                        throw new QysException(differencePayDTO.getMessage());
                    }
                }else if (difference.compareTo(new BigDecimal("0"))>0){
                    FinancePayDTO differencePayDTO = new FinancePayDTO();
                    payDTO.setUserId(rw.getUserId());
                    payDTO.setShopId(rw.getShopId());
                    differencePayDTO.setBusinessNo(rw.getOrderNo());
                    differencePayDTO.setAmountIncurred(difference.abs());
                    differencePayDTO.setDescription("申请与实际差额");
                    differencePayDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE_DIFFERENCE);
                    financeBusinessService.pay(differencePayDTO);

                    if (!payDTO.getSuccess()) {
                        throw new QysException(payDTO.getMessage());
                    }
                }
                //首次充值奖励
                boolean isFirst=rechargeWithdrawalDao.isFirstRecharge(payDTO.getShopId());
                if (isFirst) {
                    rw.setFirstRecharge(Constants.YesNoInt.YES);
                    String rewardStr = sysConfigService.getConfigKey("shop_first_recharge_reward");
                    if (rewardStr == null) {
                        rewardStr = "10";
                    }
                    FinancePayDTO rewardDTO = new FinancePayDTO();
                    rewardDTO.setUserId(Long.valueOf(payDTO.getUserId()));
                    rewardDTO.setShopId(payDTO.getShopId());
                    rewardDTO.setBusinessNo(rw.getOrderNo());
                    rewardDTO.setAmountIncurred(new BigDecimal(rewardStr));
                    rewardDTO.setDescription("Shop first recharge reward");
                    rewardDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE_FIRST_RETURN_COST);
                    financeBusinessService.pay(rewardDTO);
                    if (!rewardDTO.getSuccess()) {
                        throw new QysException(rewardDTO.getMessage());
                    }
                }
                //充值返现
                ShopRechargeGradient gradient=shopRechargeGradientService.getByAmount(payDTO.getAmountIncurred());
                if (gradient!=null){
                    FinancePayDTO returnDTO = new FinancePayDTO();
                    returnDTO.setUserId(Long.valueOf(payDTO.getUserId()));
                    returnDTO.setShopId(payDTO.getShopId());
                    returnDTO.setBusinessNo(rw.getOrderNo());
                    returnDTO.setAmountIncurred(gradient.getAmount());
                    returnDTO.setDescription("Shop recharge reward");
                    returnDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE_RETURN_COST);
                    financeBusinessService.pay(returnDTO);
                    if (!returnDTO.getSuccess()) {
                        throw new QysException(returnDTO.getMessage());
                    }
                }
            }
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_WITHDRAWAL);
            }
            financeBusinessService.pay(payDTO);

            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
//            LambdaQueryWrapper<H2ShopStatisticsInfo> shopRechargeWithdrawalQuery = Wrappers.lambdaQuery(H2ShopStatisticsInfo.class)
//                    .eq(H2ShopStatisticsInfo::getShopId, rw.getShopId());
//            List<H2ShopStatisticsInfo> h2ShopStatisticsInfos = h2ShopStatisticsInfoService.list(shopRechargeWithdrawalQuery);
//            if (CollectionUtils.isNotEmpty(h2ShopStatisticsInfos)){
//                H2ShopStatisticsInfo h2ShopStatisticsInfo=h2ShopStatisticsInfos.get(0);
//
//            }
            boolean success = rechargeWithdrawalDao.updateById(rw);
//            todo 店铺成本和收益待拆分
            if(success){
                try {
                    applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                            .shopId(rw.getShopId())
                            .eventType(ShopEventTypeEnum.SHOP_R_W_SUCCESS.getType())
                            .paramObj(ShopRechargeWithdrawalPojo.builder()
                                    .amount(rw.getAmount())
                                    .type(rw.getType())
                                    .build()
                            ).build())
                    );
                } catch (Exception e) {
                    Log.info("提现审核监听异常,FinancePayDTO:[{}]", JSON.toJSONString(payDTO));
                }
            }
            return R.ok();
        }
    }

    public R auditNoPass(AuditRw auditRw){
        synchronized (auditRw.getId()) {
            H2ShopRechargeWithdrawal rw = rechargeWithdrawalDao.getById(auditRw.getId());
            if (rw == null) {
                return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_FIND_ORDER);
            }
            if (!Objects.equals(rw.getStatus(), ShopConstant.RWStatus.WAIT_AUDIT)){
                throw new QysException(ShopMessageEnum.SHOP_ORDER_STATUS_EXCEPTION);
            }
            rw.setStatus(ShopConstant.RWStatus.AUDIT_FAIL);
            rw.setAuditDesc(auditRw.getAuditDesc());
            rw.setAuditDate(LocalDateTime.now());
            rw.setAuditUserName(SecurityUtils.getUsername());

            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(rw.getUserId()));
            payDTO.setShopId(rw.getShopId());
            payDTO.setBusinessNo(rw.getOrderNo());
            payDTO.setAmountIncurred(rw.getAmount());
            payDTO.setDescription(auditRw.getAuditDesc());
            //处理店铺余额

            payDTO.setDescription(auditRw.getAuditDesc());
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_RECHARGE.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_CANCEL);
                financeBusinessService.pay(payDTO);
                if (payDTO.getSuccess()){
                    AccountHandle handle=new AccountHandle();
                    handle.setUserId(payDTO.getUserId());
                    handle.setShopId(payDTO.getShopId());
                    handle.setPayMethod(Constant.PayMethod.BALANCE);
                    handle.setTradeTypeEnum(AccountTradeTypeEnum.OUT);
                    handle.setAccountType(AccountTypeEnum.USER_ACCOUNT.getType());
                    handle.setAmountIncurred(new BigDecimal("0"));
                    handle.setFreezeAmount(payDTO.getAmountIncurred());
                    handle.setBusinessNo(payDTO.getBusinessNo());
                    handle.setBusinessType(payDTO.getBusinessType());
                    handle.setDescription(payDTO.getDescription());
                    //查询余额
                    FinanceShopAccount account=financeShopAccountService.get(payDTO.getUserId());
                    financeShopAccountDetailService.addOtherLog(handle,account);
                }
                //不处理
            } else if (Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL);
                financeBusinessService.pay(payDTO);
            }

            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            boolean success = rechargeWithdrawalDao.updateById(rw);
            if (success&&Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL.getType(), rw.getType())) {
                try {
                    applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                            .shopId(rw.getShopId())
                            .eventType(ShopEventTypeEnum.SHOP_WAIT_WL.getType())
                            .paramObj(ShopWaitWlPojo.builder()
                                    .amount(rw.getAmount())
                                    .type(0)
                                    .build()
                            )
                            .build())
                    );
                } catch (Exception e) {
                    Log.info("提现审核监听异常,FinancePayDTO:[{}]", JSON.toJSONString(payDTO));
                }
            }
            return R.ok();
        }
    }

    public R cancel(CancelRw cancelRw){
        synchronized (cancelRw.getId()) {
            H2ShopRechargeWithdrawal rw = rechargeWithdrawalDao.getById(cancelRw.getId());
            if (rw == null) {
                return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_FIND_ORDER);
            }
            if (!Objects.equals(rw.getStatus(), ShopConstant.RWStatus.WAIT_AUDIT)){
                throw new QysException(ShopMessageEnum.SHOP_ORDER_STATUS_EXCEPTION);
            }
            rw.setStatus(ShopConstant.RWStatus.CANCEL);
            rw.setCancelDesc(cancelRw.getCancelDesc());
            rw.setCancelDate(LocalDateTime.now());


            //处理店铺余额
            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(rw.getUserId()));
            payDTO.setShopId(rw.getShopId());
            payDTO.setBusinessNo(rw.getOrderNo());
            payDTO.setAmountIncurred(rw.getAmount());
            payDTO.setDescription(cancelRw.getCancelDesc());
            payDTO.setDescription(cancelRw.getCancelDesc());
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_RECHARGE_CANCEL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_RECHARGE_CANCEL);
                financeBusinessService.pay(payDTO);
                if (payDTO.getSuccess()){
                    AccountHandle handle=new AccountHandle();
                    handle.setUserId(payDTO.getUserId());
                    handle.setShopId(payDTO.getShopId());
                    handle.setPayMethod(Constant.PayMethod.BALANCE);
                    handle.setTradeTypeEnum(AccountTradeTypeEnum.OUT);
                    handle.setAccountType(AccountTypeEnum.SHOP_ACCOUNT.getType());
                    handle.setAmountIncurred(new BigDecimal("0"));
                    handle.setFreezeAmount(payDTO.getAmountIncurred());
                    handle.setBusinessNo(payDTO.getBusinessNo());
                    handle.setBusinessType(payDTO.getBusinessType());
                    handle.setDescription(payDTO.getDescription());
                    //查询余额
                    FinanceShopAccount account=financeShopAccountService.get(payDTO.getUserId());
                    financeShopAccountDetailService.addOtherLog(handle,account);
                }
            }
            if (Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL);
                financeBusinessService.pay(payDTO);
            }

            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            boolean success = rechargeWithdrawalDao.updateById(rw);
            if (success&&Objects.equals(AccountBusinessTypeEnum.SHOP_WITHDRAWAL_CANCEL.getType(), rw.getType())) {
                try {
                    applicationContext.publishEvent(new ShopEvent(ShopEventInfo.builder()
                            .shopId(rw.getShopId())
                            .eventType(ShopEventTypeEnum.SHOP_WAIT_WL.getType())
                            .paramObj(ShopWaitWlPojo.builder()
                                    .amount(rw.getAmount())
                                    .type(0)
                                    .build()
                            )
                            .build())
                    );
                } catch (Exception e) {
                    Log.info("提现审核监听异常,FinancePayDTO:[{}]", JSON.toJSONString(payDTO));
                }
            }
            return R.ok();
        }
    }



    private void rwCheck(EditRw rw){
        if (rw==null){
            throw new QysException(ExceptionEnum.PARAM_IS_ERROR);
        }
        if (rw.getAmountIncurred()==null||rw.getAmountIncurred().compareTo(new BigDecimal("0"))!=1){
            throw new QysException(ShopMessageEnum.SHOP_AMOUNT_ERROR);
        }
        if (rw.getPayMethod()==null){
            throw new QysException(ShopMessageEnum.SHOP_PAY_METHOD_ERROR);
        }
        if (!Objects.equals(rw.getPayMethod(), ShopConstant.PayMethod.BALANCE)
                &&!Objects.equals(rw.getPayMethod(), ShopConstant.PayMethod.BANK_CARD)
                &&!Objects.equals(rw.getPayMethod(), ShopConstant.PayMethod.USDT)){
            throw new QysException(ShopMessageEnum.SHOP_PAY_METHOD_ERROR);
        }
        if (!Objects.equals(rw.getPayMethod(), ShopConstant.PayMethod.BALANCE)){
            if (rw.getCardId()==null){
                throw new QysException(ShopMessageEnum.SHOP_PAY_ACCOUNT_ERROR);
            }
        }
    }

    @Override
    public Page<RechargeVO> shopRechargeStatistics(ShopRechargeSearch query) {
        //如果没有输入任何条件
        if (!query.isExc()){
            Page<RechargeVO> page = new Page<>(query.getPageNum(), query.getPageSize());
            page = rechargeWithdrawalMapper.getShopRechargeList(page, query);
            if (CollectionUtils.isEmpty(page.getRecords())) {
                return page;
            }
            //添加其他信息
            return  buildReOtherInfo(page);
        }
        //根据用户查询条件查出符合条件的用户id
        List<Long> userIds=null;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(query.getUserDirectPush())){
            //直推
            userIds=relationService.getLowerLevels(query.getUserDirectPush(),1);
        }else if (org.apache.commons.lang3.StringUtils.isNotBlank(query.getUser3rdGeneration())){
            //三代
            List<Integer> levels=new ArrayList<>();
            levels.add(1);
            levels.add(2);
            levels.add(3);
            userIds=relationService.getLowerLevels(query.getUser3rdGeneration(),levels);
        }else if (StringUtils.isNotBlank(query.getUserUnderUmbrella())){
            //伞下
            userIds=relationService.getGreaterLevels(query.getUserUnderUmbrella(),0);
        }
        if (userIds!=null&&userIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(query.getPageNum(), query.getPageSize());
        }
        //构建用户查询条件
        UserQuery userQuery=new UserQuery();

        if (CollectionUtils.isNotEmpty(userIds)){
            //不为空，则添加默认条件 正常状态用户(店铺)，充值用户（店铺），真实用户（店铺）
            query.setShopStatus(ShopConstant.ShopStatus.IN_BUSINESS);
            query.setUserSysType(AppUserConstant.SysUserType.NORMAL);
            userQuery.setUserIds(userIds.stream().map(String::valueOf).collect(Collectors.toList()));
            query.setCharged(Constants.YesNoInt.YES);
        }
        BeanUtils.copyProperties(query,userQuery);
        //用户表查询出符合条件的id
        userQuery.setStartTime(null);
        userQuery.setEndTime(null);
        userIds=appUserService.getUserIdByQuery(userQuery);
        if (userIds!=null&&userIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(query.getPageNum(), query.getPageSize());
        }

        //余额过滤
        if (query.getBalanceStart()!=null||query.getBalanceEnd()!=null) {
            userIds=financeShopAccountService.listByUserIds(userIds, query.getBalanceStart(),query.getBalanceEnd());
            if (userIds!=null&&userIds.size()==0){
                //条件不符合，直接返回
                return new Page<>(query.getPageNum(), query.getPageSize());
            }
            userQuery.setLongUserIds(userIds);
        }

        //层级
        if(query.getStorey()!=null){
            userIds=userShopStatisticsService.getUserId(userQuery);
            if (userIds!=null&&userIds.size()==0){
                //条件不符合，直接返回
                return new Page<>(query.getPageNum(), query.getPageSize());
            }
            userQuery.setLongUserIds(userIds);
        }
        query.setUserIds(userIds);
        //店铺查询条件
        ShopQuery shopQuery=new ShopQuery();
        BeanUtils.copyProperties(query,shopQuery);
        List<Long> shopIds=shopBaseService.getShopIdByQuery(shopQuery);
        if (shopIds!=null&&shopIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(query.getPageNum(), query.getPageSize());
        }
        query.setShopIds(shopIds);

        Page<RechargeVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        page = rechargeWithdrawalMapper.getShopRechargeList(page, query);
        if (CollectionUtils.isEmpty(page.getRecords())){
            return page;
        }
        return buildReOtherInfo(page);
    }

    private Page<RechargeVO> buildReOtherInfo(Page<RechargeVO> page){
        //todo IP信息
        return page;
    }



    @Override
    public Page<ShopWithdrawalsStatisticsVO> shopWithdrawalsStatistics(ShopWlSearch rwSearch) {
        //如果没有输入任何条件
        if (!rwSearch.isExc()){
            Page<ShopWithdrawalsStatisticsVO> page = new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
            page = rechargeWithdrawalMapper.withdrawalsPage(page, rwSearch);
            if (CollectionUtils.isEmpty(page.getRecords())) {
                return page;
            }
            //添加其他信息
            return  buildWlOtherInfo(page);
        }
        //根据用户查询条件查出符合条件的用户id
        List<Long> userIds=null;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(rwSearch.getUserDirectPush())){
            //直推
            userIds=relationService.getLowerLevels(rwSearch.getUserDirectPush(),1);
        }else if (org.apache.commons.lang3.StringUtils.isNotBlank(rwSearch.getUser3rdGeneration())){
            //三代
            List<Integer> levels=new ArrayList<>();
            levels.add(1);
            levels.add(2);
            levels.add(3);
            userIds=relationService.getLowerLevels(rwSearch.getUser3rdGeneration(),levels);
        }else if (org.apache.commons.lang3.StringUtils.isNotBlank(rwSearch.getUserUnderUmbrella())){
            //伞下
            userIds=relationService.getGreaterLevels(rwSearch.getUserUnderUmbrella(),0);
        }
        if (userIds!=null&&userIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
        }


        //构建用户查询条件
        UserQuery userQuery=new UserQuery();
        BeanUtils.copyProperties(rwSearch,userQuery);
        if (CollectionUtils.isNotEmpty(userIds)){
            //不为空，则添加默认条件 正常状态用户(店铺)，充值用户（店铺），真实用户（店铺）
            rwSearch.setShopStatus(ShopConstant.ShopStatus.IN_BUSINESS);
            userQuery.setUserSysType(AppUserConstant.SysUserType.NORMAL);
            userQuery.setSupUserName(null);
            userQuery.setPoxUserName(null);
            userQuery.setUserIds(userIds.stream().map(String::valueOf).collect(Collectors.toList()));

            rwSearch.setCharged(Constants.YesNoInt.YES);
        }
        //用户表查询出符合条件的id
        userQuery.setStartTime(null);
        userQuery.setEndTime(null);
        userIds=appUserService.getUserIdByQuery(userQuery);
        if (userIds!=null&&userIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
        }

        //余额过滤
        if (rwSearch.getBalanceStart()!=null||rwSearch.getBalanceEnd()!=null) {
            userIds=financeShopAccountService.listByUserIds(userIds, rwSearch.getBalanceStart(),rwSearch.getBalanceEnd());
            if (userIds!=null&&userIds.size()==0){
                //条件不符合，直接返回
                return new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
            }
        }

        //层级
        if(rwSearch.getStorey()!=null){
            userQuery.setStorey(rwSearch.getStorey());
            userQuery.setLongUserIds(userIds);
            userIds=userShopStatisticsService.getUserId(userQuery);
            if (userIds!=null&&userIds.size()==0){
                //条件不符合，直接返回
                return new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
            }
        }

        //店铺查询条件
        ShopQuery shopQuery=new ShopQuery();
        BeanUtils.copyProperties(rwSearch,shopQuery);
        shopQuery.setUserIds(userIds);
        List<Long> shopIds=shopBaseService.getShopIdByQuery(shopQuery);
        if (shopIds!=null&&shopIds.size()==0){
            //条件不符合，直接返回
            return new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
        }

        rwSearch.setShopIds(shopIds);
        //查询订单
        Page<ShopWithdrawalsStatisticsVO> page = new Page<>(rwSearch.getPageNum(), rwSearch.getPageSize());
        Page<ShopWithdrawalsStatisticsVO> resultPage = rechargeWithdrawalMapper.withdrawalsPage(page, rwSearch);
        if (CollectionUtils.isEmpty(resultPage.getRecords())){
            return resultPage;
        }
        return buildWlOtherInfo(page);
    }

    private Page<ShopWithdrawalsStatisticsVO> buildWlOtherInfo(Page<ShopWithdrawalsStatisticsVO> page){
        List<Integer> channelIds=page.getRecords().stream().map(ShopWithdrawalsStatisticsVO::getChannelId).collect(Collectors.toList());
        List<String> userIds=page.getRecords().stream().map(ShopWithdrawalsStatisticsVO::getUserId).map(String::valueOf).collect(Collectors.toList());
        List<String> ips=page.getRecords().stream().map(ShopWithdrawalsStatisticsVO::getApplyIp).collect(Collectors.toList());
        //提现通道
        List<H2Channel> channels= channelService.listByIds(channelIds);
        Map<Integer,String> channelMap=new HashMap<>() ;
        if (CollectionUtils.isNotEmpty(channels)){
            channelMap=channels.stream().collect(Collectors.toMap(H2Channel::getId,H2Channel::getChannelName));
        }
        //用户
        List<H2AppUser>  users= appUserService.listByIds(userIds);
        Map<String,H2AppUser> userMap=new HashMap<>() ;
        if (CollectionUtils.isNotEmpty(users)){
            userMap=users.stream().collect(Collectors.toMap(H2AppUser::getId,v->v));
        }
        //ip
        Map<String,Integer> ipMap=new HashMap<>() ;
        if (CollectionUtils.isNotEmpty(ips)) {
            List<IpOperateStatistics> ipList = ipOperateStatisticsService.getbyIps(ips,1);
            if (CollectionUtils.isNotEmpty(ipList)){
                ipMap=ipList.stream().collect(Collectors.toMap(IpOperateStatistics::getIp,IpOperateStatistics::getNum));
            }
        }
        for (ShopWithdrawalsStatisticsVO vo:page.getRecords()){
            vo.setSuperiorName(userMap.get(String.valueOf(vo.getUserId())).getSuperiorName());
            vo.setWithdrawalChannel(channelMap.get(vo.getChannelId()));
            vo.setSameRegisterIpNum(ipMap.get(vo.getApplyIp()));
        }

        //todo
        return page;
    }

    @Override
    public Map getTotalRe(Long shopId){
        return rechargeWithdrawalMapper.getTotalRe(shopId);
    }
    @Override
    public Map getTotalWl(Long shopId){
        return rechargeWithdrawalMapper.getTotalWl(shopId);
    }

    @Override
    public BigDecimal getTotalWaitWl(Long shopId){
        return rechargeWithdrawalMapper.getTotalWaitWl(shopId);
    }
}
